.model tiny

.data
Msg_new_line:	db 0dh, 0ah, '$'
Msg_error:	db 'An error occurred!$'
Msg_enter_numb:	db 'Enter the number: $'
Msg_your_numb:	db 'Your number is: $'
Msg_chz_in:	db 'Please, enter the input numeric system (b/d/h): $'
Msg_chz_out:	db 'Please, enter the output numeric system (b/d/h): $'

.code

org 100h

jumps
locals @@

Start:	
	
Main		proc
		
		xor ax, ax
		xor bx, bx
		xor cx, cx
		xor dx, dx
		xor si, si
		
		call CHZ_IN
		call CHZ_OUT
		
		call Exit
		
		ret
		
		endp

;===============================================================================
; Writes an invitation to choose input numeral system and calls an appropriate
;	procedure to deal with input number in this system
; 
; Entry: None
; Exit:  AL - the number base
; 
; Destr: AX DX
;===============================================================================
;\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\

CHZ_IN		proc
	
@@begin:	call Msg_enter
		
		mov ah, 9h
		mov dx, offset Msg_chz_in
		int 21h
		
		mov ah, 0h	; keyboard input: scan code in ah, ASCII in al
		int 16h
			
		mov ah, 0eh	; in al character to write
		int 10h
		
		cmp al, 'b'
		jz @@Input2
		cmp al, 'B'
		jz @@Input2
		
		cmp al, 'd'
		jz @@Input10
		cmp al, 'D'
		jz @@Input10
		
		cmp al, 'h'
		jz @@Input16
		cmp al, 'H'
		jz @@Input16
		
		call Msg_enter
		
		mov ah, 09h
		mov dx, offset Msg_error
		int 21h
		
		jmp @@begin
	
@@Input2:	call Input2
		jmp @@Exit

@@Input10:	call Input10
		jmp @@Exit

@@Input16:	call Input16
		jmp @@Exit
	
@@Exit:		ret
	
		endp
		
;/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/
;===============================================================================

	
;===============================================================================
; Recognise number as a binary number and save it into bx
; 
; Entry: None
; Exit:  BX - entered number
; 
; Destr: AX BX DX
;===============================================================================
;\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\

Input2		proc
		
		call Msg_enter
		
		mov ah, 9h
		mov dx, offset Msg_enter_numb
		int 21h
		
@@In2next:	mov ah, 0h
		int 16h
		
		cmp ah, 1ch	; scan code of "Enter key"
		je @@Exit
		
		mov ah, 0eh
		int 10h
		
		shl bx, 1h
		xor ah, ah	;
		sub al, 30h	; make a digit from an ASCII character
		or bx, ax
		
		jmp @@In2next
		
@@Exit:		ret
		
		endp
		
;/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/
;===============================================================================


;===============================================================================
; Recognise number as a decimal number and save it into bx
; 
; Entry: None
; Exit:  BX - entered number
; 
; Destr: AX BX DX
;===============================================================================
;\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\

Input10		proc
	
		call Msg_enter
		
		mov ah, 9h
		mov dx, offset Msg_enter_numb
		int 21h
		
@@In10next:	mov ah, 0h
		int 16h
		
		cmp ah, 1ch	; scan code of "Enter key"
		je @@Exit
		
		mov ah, 0eh
		int 10h
		
		sub al, 30h
		xor ah, ah
		
		xchg ax, bx	; only for (bx * 10)
		mov dx, 0ah
		mul dx
		xchg ax, bx
		
		add bx, ax
		
		jmp @@In10next	
		
@@Exit:		ret
		
		endp
		
;/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/
;===============================================================================


;===============================================================================
; Recognise number as a heximal number and save it into bx
; 
; Entry: None
; Exit:  BX - entered number
; 
; Destr: AX BX DX
;===============================================================================
;\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\

Input16		proc
		
		call Msg_enter
		
		mov ah, 9h
		mov dx, offset Msg_enter_numb
		int 21h
		
@@In16next:	mov ah, 0h
		int 16h
		
		cmp ah, 1ch	; scan code of "Enter key"
		je @@Exit
		
		mov ah, 0eh
		int 10h
		
		; cmp al, 3ah
		cmp al, '9' + 1	; digit?
		jb @@In123
		
		cmp al, 'F' + 1	; capital letter? (mean hex digit above 9)
		jb @@InCapABC
		
		cmp al, 'f' + 1	; small letter?   (mean hex digit above 9)
		jb @@Inabc
		
		jmp @@In16next
		
@@Inabc:	sub al, 57h	; to make a number from an ASCII code
		jmp @@Contin16
		
@@InCapABC:	sub al, 37h
		jmp @@Contin16
		
@@In123:	sub al, 30h
	
@@Contin16:	xor ah, ah
		
		xchg ax, bx
		mov dx, 10h
		mul dx
		xchg ax, bx
		
		add bx, ax
		
		jmp @@In16Next
		
@@Exit:		ret
		
		endp
	
;/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/
;===============================================================================

;===============================================================================
; Writes an invitation to choose output numeral system and calls an appropriate
;	procedure to convert and print the number in chosen output system
; 
; Entry: None
; Exit:  AL - the number base
; 
; Destr: AX DX
;===============================================================================
;\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\

CHZ_OUT		proc
		
@@begin:	call Msg_enter
		
		mov ah, 9h
		mov dx, offset Msg_chz_out
		int 21h
		
		mov ah, 0h
		int 16h
		
		mov ah, 0eh
		int 10h
		
		cmp al, 'b'
		jz @@Bin
		cmp al, 'B'
		jz @@Bin
		
		cmp al, 'd'
		jz @@Dec
		cmp al, 'D'
		jz @@Dec
		
		cmp al, 'h'
		jz @@Hex
		cmp al, 'H'
		jz @@Hex
		
		call Msg_enter
		
		mov ah, 9h
		mov dx, offset Msg_error
		int 21h
		
		jmp @@begin
		
@@Bin:		call Conv_to_bin&Print
		jmp @@Exit
		
@@Dec:		call Conv_to_dec&Print
		jmp @@Exit
		
@@Hex:		call Conv_to_hex&Print
		jmp @@Exit

@@Exit:		ret
		
		endp

;/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/
;===============================================================================


;===============================================================================
; Converts number to binary numeral system and prints them in stdout
; 
; Entry: BX - number to convert
; Exit:  None
;
; Destr: AX BX CL DX SI 
;===============================================================================
;\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\

Conv_to_bin&Print	proc
		
		call Msg_enter
		
		mov ah, 9h
		mov dx, offset Msg_your_numb
		int 21h
		
		xor si, si	; zero flag for LEAD_0
		mov cl, 0fh	; set the counter
		mov dx, 0ffffh	; set the mask
	
@@Conv2:	test dx, dx
		jz @@Exit
		
		mov ax, bx	; copy
		shr ax, cl	; choose digits from the beginning
		
		test si, si
		jnz @@Next21
		
		call LEAD_0
		test al, al
		jz @@Next22
		
@@Next21:	add al, 30h	; conv to ASCII
		call Print
		
@@Next22:	dec cl		; count--
		shr dx, 1h	; mask >> 1
		
		and bx, dx	; del 1st digit
		
		jmp @@Conv2
		
@@Exit:		ret

		endp
		
;/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/
;===============================================================================


;===============================================================================
; Converts number to heximal numeral system and prints them in stdout
; 
; Entry: BX - number to convert
; Exit:  None
;
; Destr: AX BX CL DX SI 
;===============================================================================
;\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\

Conv_to_hex&Print	proc
		
		call Msg_enter
		
		mov ah, 09h
		mov dx, offset Msg_your_numb
		int 21h
		
		xor si, si	; zero flag for LEAD_0
		mov cl, 0ch	; set the step of shifting
		mov dx, 0ffffh	; set the mask
		
@@Conv16:	test dx, dx
		jz @@Exit
		
		mov ax, bx	; copy
		shr ax, cl
		
		test si, si		; 
		jnz @@Not_lead_zero	; for
					; leading
		call LEAD_0		; zeros
		test ax, ax		; 
		jz @@Next16		; 
		
@@Not_lead_zero:cmp ax, 0ah	; convert to ASCII
		jae @@THEABC

@@THE123:	add ax, 30h
		jmp @@Print
		
@@THEABC:	add ax, 37h
		
@@Print:	call Print
		
@@Next16:	sub cl, 4h	; dec the step
		shr dx, 4h	; dec the mask
		and bx, dx
		
		jmp @@Conv16
		
@@Exit:		ret
		
		endp

;/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/
;===============================================================================


;===============================================================================
; Converts number to decimal numeral system and prints them in stdout
; 
; Entry: BX - number to convert
; Exit:  None
;
; Destr: AX BX CX DX SI 
;===============================================================================
;\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\

Conv_to_dec&Print	proc
		
		call Msg_enter
		
		mov ah, 09h
		mov dx, offset Msg_your_numb
		int 21h
		
		mov ax, bx	; copy
		xor dx, dx
		mov bx, 2710h	; 10000d - divider
		mov cx, 0ah	; 10d - divider for divider
		xor si, si	; flag for leading zeros
		
@@Conv10:	test bx, bx
		jz @@Exit
		
		div bx		; ax - divident, dx - quotient
		
		test si, si
		jnz @@Print
		
		call LEAD_0
		test al, al
		jz @@Next10
			
@@Print:	add al, 30h
		call Print
		
@@Next10: ; I need to divide the divider (now in bx) but 'div' uses ax and dx,
	  ; in dx I now have my number w/o 1st digit,
	  ; so I need to save it
	  ; and finally place number in ax, divider in bx
		
		mov ax, bx	; move divider to use 'div'
		mov bx, dx	; to save quotient
		
		xor dx, dx	; delete trash
		div cx		; divide the divider, store it in ax
		mov dx, bx	; temporary move number in free register
		
		mov bx, ax	; move divided divider
		mov ax, dx	; restore the number
		
		xor dx, dx	; delete trash for further dividing
			
		jmp @@Conv10
		
@@Exit:		ret
		
		endp

;/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/
;===============================================================================


;===============================================================================
; Writes an Enter to the stdout
; 
; Entry: None
; Exit:  Enter to the stdout
;
; Destr: AH DX 
;===============================================================================
;\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\

Msg_enter	proc

		mov ah, 9h
		mov dx, offset Msg_new_line
		int 21h

		ret

		endp

;/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/
;===============================================================================


;===============================================================================
; Checks if the number has leading zeros and sets SI = 1 if there is first
; 	non-zero element
; 
; Entry: AL = a digit of a number
; Exit:  SI = 1 if there is first non-zero element
;	 SI = 0 if this is zero element and before was leading zeroes too
; 
; Destr: SI
;===============================================================================
;\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\
		
LEAD_0		proc
		
		test al, al
		jz @@Exit
		
		mov si, 1h
		
@@Exit:		ret
		
		endp

;/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/
;===============================================================================


;===============================================================================
; Prints a digit to stdout
; 
; Entry: AL = digit to print (ASCII code)
; Exit:  None 
;
; Destr: AH
;===============================================================================
;\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\

Print		proc
		
		mov ah, 0eh
		int 10h
		ret
		
		endp
		
;/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/
;===============================================================================


;===============================================================================
; Terminates the program
; 
; Entry: None
; Exit:  None
; 
; Destr: AX
;===============================================================================
;\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\

Exit		proc
		
		mov ax, 4c00h
		int 21h
		ret
		
		endp
		
;/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/
;===============================================================================


end		Start

;===============================================================================
; 
;===============================================================================
;\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\/-\


;/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/\-/
;===============================================================================

